#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>


#define HYDRA_HOME ".hydra"
#define ENVS_DIR "environments"
#define MAX_PATH 4096

int directory_exists(const char *path) {
    struct stat st;
    return (stat(path, &st) == 0 && S_ISDIR(st.st_mode));
}

void remove_directory(const char *path) {
    DIR *dir = opendir(path);
    if (!dir) {
        perror("Error opening directory");
        exit(EXIT_FAILURE);
    }

    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
            continue;

        char full_path[MAX_PATH];
        snprintf(full_path, sizeof(full_path), "%s/%s", path, entry->d_name);

        struct stat st;
        if (lstat(full_path, &st) == -1) {
            perror("lstat failed");
            continue;
        }

        if (S_ISDIR(st.st_mode))
            remove_directory(full_path);
        else
            unlink(full_path);
    }
    closedir(dir);
    rmdir(path);
}

int is_valid_name(const char *name) {
    for (size_t i = 0; i < strlen(name); i++) {
        if (!isalnum(name[i]) && name[i] != '_' && name[i] != '-')
            return 0;
    }
    return 1;
}

void handle_create(const char *env_name) {
    if (!is_valid_name(env_name)) {
        fprintf(stderr, "Invalid environment name: %s\n", env_name);
        exit(EXIT_FAILURE);
    }

    char base_path[MAX_PATH];
    snprintf(base_path, sizeof(base_path), "%s/%s", getenv("HOME"), HYDRA_HOME);

    // 创建基础目录结构
    if (!directory_exists(base_path)) {
        if (mkdir(base_path, 0755) == -1) {
            perror("Error creating hydra home directory");
            exit(EXIT_FAILURE);
        }
        printf("Created hydra home at %s\n", base_path);
    }

    // 确保environments目录存在
    char envs_dir[MAX_PATH];
    snprintf(envs_dir, sizeof(envs_dir), "%s/%s", base_path, ENVS_DIR);
    if (!directory_exists(envs_dir)) {
        if (mkdir(envs_dir, 0755) == -1) {
            perror("Error creating environments directory");
            exit(EXIT_FAILURE);
        }
    }

    // 创建具体环境目录
    char env_path[MAX_PATH];
    snprintf(env_path, sizeof(env_path), "%s/%s", envs_dir, env_name);

    if (directory_exists(env_path)) {
        fprintf(stderr, "Environment %s already exists\n", env_name);
        exit(EXIT_FAILURE);
    }

    if (mkdir(env_path, 0755) == -1) {
        perror("Error creating environment directory");
        exit(EXIT_FAILURE);
    }

    // 验证系统Python路径
    const char *python_path = "/usr/bin/python3";
    struct stat st;
    if (stat(python_path, &st) != 0 || !S_ISREG(st.st_mode)) {
        fprintf(stderr, "System Python not found at %s\n", python_path);
        remove_directory(env_path);  // 清理已创建的目录
        exit(EXIT_FAILURE);
    }

    // 创建bin目录
    char env_bin[MAX_PATH];
    snprintf(env_bin, sizeof(env_bin), "%s/bin", env_path);
    if (mkdir(env_bin, 0755) == -1) {
        perror("Error creating bin directory");
        remove_directory(env_path);
        exit(EXIT_FAILURE);
    }

    // 创建符号链接
    char link_path[MAX_PATH];
    snprintf(link_path, sizeof(link_path), "%s/python", env_bin);
    if (symlink(python_path, link_path) == -1) {
        perror("Error creating python symlink");
        remove_directory(env_path);
        exit(EXIT_FAILURE);
    }

    printf("Successfully created environment '%s'\n", env_name);
    printf("Python path: %s -> %s\n", link_path, python_path);
    printf("Environment path: %s\n", env_path);
    printf("To activate the environment, run 'hydra activate %s'\n", env_name);
}

void handle_activate(const char *env_name) {
    char env_path[MAX_PATH];
    snprintf(env_path, sizeof(env_path), "%s/%s/%s/%s", 
             getenv("HOME"), HYDRA_HOME, ENVS_DIR, env_name);

    if (!directory_exists(env_path)) {
        fprintf(stderr, "Environment %s not found\n", env_name);
        exit(EXIT_FAILURE);
    }

    #pragma region 修改终端的PS1来方便辨识当前环境，目前没法正确显示
    // const char *old_ps1 = getenv("PS1");
    // char command[MAX_PATH];
    // snprintf(command, sizeof(command), "PS1='(hydra) %s' bash --norc", old_ps1);
    // system(command);
    #pragma endregion

}

void handle_deactivate() {

}

void handle_list_envs() {
    char env_dir[MAX_PATH];
    snprintf(env_dir, sizeof(env_dir), "%s/%s/%s", 
             getenv("HOME"), HYDRA_HOME, ENVS_DIR);

    DIR *dir = opendir(env_dir);
    if (!dir) {
        perror("Error opening environments directory");
        exit(EXIT_FAILURE);
    }

    printf("Available environments:\n");
    struct dirent *entry;
    while ((entry = readdir(dir)) != NULL) {
        if (entry->d_type == DT_DIR && 
            strcmp(entry->d_name, ".") != 0 &&
            strcmp(entry->d_name, "..") != 0) {
            printf("  %s\n", entry->d_name);
        }
    }
    closedir(dir);
}

void print_help() {
    printf("Usage: hydra <command> [options]\n\n"
           "Commands:\n"
           "  create <env_name>\t\tCreate new environment\n"
           "  activate <env_name>\t\tActivate environment\n"
           "  deactivate\t\t\tDeactivate current environment\n"
           "  remove <env_name>\t\tRemove environment\n"
           "  list envs\t\t\tList all environments\n"
           "  info\t\t\t\tShow environment info\n"
           "  help\t\t\t\tShow this help message\n");
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        print_help();
        return EXIT_FAILURE;
    }

    const char *cmd = argv[1];
    if (strcmp(cmd, "create") == 0) {
        if (argc != 3) {
            fprintf(stderr, "Error: Missing environment name\n");
            print_help();
            return EXIT_FAILURE;
        }
        handle_create(argv[2]);
    } else if (strcmp(cmd, "activate") == 0) {
        if (argc != 3) {
            fprintf(stderr, "Error: Missing environment name\n");
            print_help();
            return EXIT_FAILURE;
        }
        handle_activate(argv[2]);
    } else if (strcmp(cmd, "deactivate") == 0) {
        handle_deactivate();
    } else if (strcmp(cmd, "remove") == 0) {
        if (argc != 3) {
            fprintf(stderr, "Error: Missing environment name\n");
            print_help();
            return EXIT_FAILURE;
        }
        char env_path[MAX_PATH];
        snprintf(env_path, sizeof(env_path), "%s/%s/%s/%s", 
                 getenv("HOME"), HYDRA_HOME, ENVS_DIR, argv[2]);
        remove_directory(env_path);
        printf("Removed environment %s\n", argv[2]);
    } else if (strcmp(cmd, "list") == 0) {
        if (argc != 3) {
            fprintf(stderr, "Error: Missing list type\n");
            print_help();
            return EXIT_FAILURE;
        }
        if (strcmp(argv[2], "envs") == 0) {
            handle_list_envs();
        } else {
            fprintf(stderr, "Error: Invalid list type\n");
            print_help();
            return EXIT_FAILURE;
        }
    } else if (strcmp(cmd, "help") == 0) {
        print_help();
    } else {
        fprintf(stderr, "Error: Unknown command %s\n", cmd);
        print_help();
        return EXIT_FAILURE;
    }

    return EXIT_SUCCESS;
}